package battleGame;

import java.util.Vector;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

public class Army 
{
	
	enum ArmyState { searchTreasure, killThem, protectTreasure, MAX };
	enum WarriorCommand{ none, searchFlag, attack, flyAway, move, standBy, defend, MAX };
	
	Vector<Warrior> listSoldiers;
	Vector<Warrior> listArchers;
	ArmyState state;
	
	Vector< GameObject > actualSight;
	Vector< DamageToken > actualDamageReport;
	Vector< GameObject > renderList;
	
	int idArmy;
	
	WarFlag flag;
	//Vector2 flagPosition;

	public Army(int s, int a, int id )
	{
		idArmy = id;
		state = ArmyState.searchTreasure;
		
		listSoldiers = new Vector<Warrior>(1,1);
		listArchers = new Vector<Warrior>(1,1);
		
		//create listSoldiers
		switch(id)
		{
		
		case 1:
			for( ; s > 0; s-- )
				listSoldiers.add( new Soldier( 16, 1, id, this ) );
			for( ; a > 0; a-- )
				listArchers.add( new Archer( 16, 1, id, this ) );
		 break;
		
		case 2:
			for( ; s > 0; s-- )
				listSoldiers.add( new Soldier( 1, 24, id, this ) );
			for( ; a > 0; a-- )
				listArchers.add( new Archer( 1, 24, id, this ) );
			break;
		 
		}
		
		renderList = new Vector< GameObject >();
		renderList.addAll( listSoldiers );
		renderList.addAll( listArchers );
	}
	
	//Game Logic pedira una lista de guerreros de este ejercito
	public Vector<Warrior> getCharacterList()
	{
		Vector<Warrior> nuevaLista;
		for( int i = 0; i < listSoldiers.size(); i ++)
			if( listSoldiers.get( i ).GetState() == Warrior.WarriorState.death )
				listSoldiers.remove( i-- );
		nuevaLista = new Vector<Warrior>( listSoldiers );
		for( int i = 0; i < listArchers.size(); i ++)
			if( listArchers.get( i ).GetState() == Warrior.WarriorState.death )
				listArchers.remove( i-- );
		nuevaLista.addAll( listArchers );
		return nuevaLista;		
	}
	
	public Vector< GameObject > getRenderList()
	{
		return renderList;
	}
	
	//GameLogic reportara que es lo que este ejercito puede ver a traves de sus soldados
	public void setActualSight( Vector< GameObject > reportedSight )
	{
		actualSight = reportedSight;
	}
	
	//GameLogic hara un reporte de dagnos de miembros del ejercito
	public void setDamage( Vector< DamageToken > damageReport )
	{
		actualDamageReport = damageReport;
	}
	
	//Uno por frame, aqui sucede el procesamiento del ejercito
	public void update()
	{
		if( this.idArmy == 1 )
			team1Update();
		else
			team2Update();
	}
	
	void team1Update()
	{
		//El ejercito solo se dedica a buscar la bandera y protegerla
		if( state == ArmyState.searchTreasure )
		{			
			flag = (WarFlag) isFlagFound();
			if( flag != null )
			{
				state = ArmyState.protectTreasure;
				sendCommandToEveryone( WarriorCommand.defend,
									   flag.position,
									   true /*forced*/ );
			}
			else
			{
				Vector2 posicionPromedio;
				posicionPromedio = Utils.promediarPosiciones( this.listSoldiers );
				sendCommandToEveryone( WarriorCommand.searchFlag, posicionPromedio, false /*forced*/ );
			}
		}
		else if( state == ArmyState.protectTreasure )
		{
			sendCommandToEveryone( WarriorCommand.defend,
					   flag.position,
					   false /*forced*/ );			
		}
	}
	
	void team2Update()
	{
		//El equipo dos se dedicara a destruir todo enemigo que encuentre
		
		if( state == ArmyState.searchTreasure )
		{
			Warrior enemy = isEnemyFound();
			flag = (WarFlag) isFlagFound();
			Vector2 commandPosition = null;
			if( flag != null )
			{
				state = ArmyState.protectTreasure;
				commandPosition = flag.position;
			}
			
			if( enemy != null )
			{
				state = ArmyState.killThem;
				commandPosition = enemy.position;
			}
			
			if( commandPosition != null )
			{
				sendCommandToEveryone( WarriorCommand.attack,
									   commandPosition,
									   true /*forced*/ );
			}
			else
			{
				//keep the same state
				Vector2 posicionPromedio;
				posicionPromedio = Utils.promediarPosiciones( this.listSoldiers );
				sendCommandToEveryone( WarriorCommand.searchFlag, posicionPromedio, false /*forced*/ );
			}			
		}
		else if( state == ArmyState.protectTreasure )
		{
			Warrior enemy = isEnemyFound();
			if( enemy != null )
			{
				state = ArmyState.killThem;
				sendCommandToEveryone( WarriorCommand.attack,
										enemy.position,
										true /*forced*/ );
			}
			else if( flag != null )
			{
				//keep the same state
				sendCommandToEveryone( WarriorCommand.attack,
										flag.position,
										false /*forced*/ );
			}
		}
		else if( state == ArmyState.killThem )
		{
			Warrior enemy = isEnemyFound();
			if( flag == null )
				flag = (WarFlag) isFlagFound();
			
			if( enemy != null )
			{
				//keep the same state
				sendCommandToEveryone( WarriorCommand.attack,
									   enemy.position,
									   true /*forced*/ );
			}
			else if( flag != null )
			{
				state = ArmyState.protectTreasure;
				sendCommandToEveryone( WarriorCommand.attack,
									   flag.position,
									   true /*forced*/ );
			}
			else
			{
				state = ArmyState.protectTreasure;
				Vector2 posicionPromedio;
				posicionPromedio = Utils.promediarPosiciones( this.listSoldiers );
				sendCommandToEveryone( WarriorCommand.searchFlag, posicionPromedio, true /*forced*/ );
			}
		}
		
	}
	
	GameObject isFlagFound()
	{
		for( int i = 0; i < actualSight.size(); i++ )
		{
			if( actualSight.get( i ) instanceof WarFlag )
			{
				System.out.print( "" + idArmy + ". Encontre la bandera" );
				return actualSight.get( i );
			}
		}
		return null;
	}
	
	void sendCommandToEveryone( WarriorCommand command, Vector2 position, boolean forced )
	{
		for( int i = 0; i < listSoldiers.size(); i++ )
		{
			Soldier soldier = (Soldier)listSoldiers.get( i );
			if( forced || soldier.GetState() == Warrior.WarriorState.waiting )
			{
				soldier.order( command, position );
			}
		}
		for( int i = 0; i < listArchers.size(); i++ )
		{
			Archer archer = (Archer)listArchers.get( i );
			if( forced || archer.GetState() == Warrior.WarriorState.waiting )
			{
				archer.order( command, position );
			}
		}
	}
	
	Warrior isEnemyFound()
	{
		for( int i = 0; i < actualSight.size(); i++ )
		{
			if( actualSight.get( i ) instanceof Warrior )
			{
				return (Warrior)actualSight.get( i );
			}
		}
		return null;		
	}
	
	void warriorDeath( Warrior cadaver )
	{
/*		if( cadaver instanceof Soldier )
			this.listSoldiers.remove( cadaver );
		else if( cadaver instanceof Archer )
			this.listArchers.remove( cadaver );
			*/
	}
}
